/**
 *  hw_timer.c - Hardware interfaces for TIMER driver.
 *
 *  Copyright (C) 2008-2010 ZhangHu
 *  All rights reserved.
 *  E-MAIL: anmnmnly@gmail.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "include/irq.h"
#include "drivers/timer.h"

#include "regdef.h"
#include "hw_timer.h"
#include "init_target.h"


static timer_duty_cycle_t default_arg;


void timer_isr(void)
{
}



void stop_timer(void)
{
    rTCON &= ~0x1000;
}



void start_timer(void)
{
    rTCON |= 0x1000;
}



// cycle: the Hz of timer.
// high: the duration of high level. (%).
void change_duty_cycle (timer_duty_cycle_t *arg)
{
    if(arg == NULL) {
        return;
    }

    if(arg->high_duration > 100) {
		arg->high_duration = 100;
    }

    rTCON &= 0xFFFF0FFF;        // clear manual update bit, stop Timer2.
	rTCFG0 &= 0xFFFF00FF;       // set Timer 2&3 prescaler 0.
	rTCFG1 &= 0xFFFFF0FF;       // set Timer 2 MUX 1/16.
	rTCFG1 |= 0x00000300;
    // if set inverter off, when TCNT2<=TCMP2, TOUT is high, TCNT2>TCMP2,
    // TOUT is low. if set inverter on, when TCNT2<=TCMP2, TOUT is low,
    // TCNT2>TCMP2, TOUT is high.
    rTCNTB2	= arg->cycle;
	rTCMPB2 = (rTCNTB2 * (100 - arg->high_duration)) / 100;
	rTCON |= 0x00002000;        // manual update.
	rTCON &= 0xFFFF0FFF;        // clear manal update bit.
	rTCON |= 0x00008000;        // auto reload, inverter off.
}



void init_timer(void)
{
    default_arg.cycle = 1000;
    default_arg.high_duration = 50;

    // Initial port
    rPCONE &= 0x3F3FF;
    rPCONE |= 0x00800;
    rPUPE = 0x20;

    // Install timer interruption routine.
    isr_install(TIMER_ISR_NUM, 0, timer_isr);
    rINTMSK &= 0x03FFF7FF;  /* unmask timer2 interrupt */

    change_duty_cycle(&default_arg);
}

